﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using System.Net.Mail;
using System.Diagnostics;

namespace QueueManagerHelper
{
    public struct NameStruct
    {
        public string FirstName;
        public string LastName;
    }

    public enum PartType
    {
        Fullname,
        FirstName,
        LastName,
        CompanyName,
        Url
    }

    public class UtilityHelper
    {
        public static string StripPunctuation(string stringToStrip)
        {
            //Remove any punctuation from a string
            StringBuilder strippedString = new StringBuilder(stringToStrip.Length);
            foreach (char curChar in stringToStrip)
                if (!Char.IsPunctuation(curChar) &&
                    (Char.IsLetter(curChar) || Char.IsNumber(curChar) || Char.IsWhiteSpace(curChar)))
                    strippedString.Append(curChar);
            return strippedString.ToString();
        }

        public static string StripTagsFromString(string source)
        {
            try
            {
                char[] array = new char[source.Length];
                int arrayIndex = 0;
                bool inside = false;
                for (int i = 0; i < source.Length; i++)
                {
                    char let = source[i];
                    if (let == '<')
                    {
                        inside = true;
                        continue;
                    }
                    if (let == '>')
                    {
                        inside = false;
                        continue;
                    }
                    if (!inside)
                    {
                        array[arrayIndex] = let;
                        arrayIndex++;
                    }
                }
                source = new string(array, 0, arrayIndex);
                return source;
            }
            catch (Exception)
            {
                return source;
            }
        }

        private static string newLinePlaceHolder = "~";
        public static string CleanHTML(string Source, Dictionary<string, Regex[]> CleanerExpressions)
        {
            string originalSource = Source;
            try
            {
                if (Source == null)
                    return string.Empty;
                //Remove the \n and \t values from the string
                Source = Source.Replace(Convert.ToChar(10).ToString(), newLinePlaceHolder);
                Source = Source.Replace(Convert.ToChar(9).ToString(), string.Empty);
                //Replace certain tag values with text equivalents
                Source = ReplaceTagValues(Source);
                //completely remove certain tags as well as their content
                Source = RemoveTagsFromString(Source, CleanerExpressions);
                //Strip all remaining tags
                Source = UtilityHelper.StripTagsFromString(Source);
                //Replace HTML values with text equivalents (i.e. &lt; = < etc.)
                Source = HttpUtility.HtmlDecode(Source);
                //Replace the non-breaking space with a normal space: we'd rather work with a space in some of the following lines of code
                Source = Source.Replace(Convert.ToChar(160).ToString(), " ");
                //remove initial NewLines
                while (Source.StartsWith(newLinePlaceHolder))
                    Source = Source.Substring(1);
                //remove NewLine + " "
                while (Source.Contains(newLinePlaceHolder + " "))
                    Source = Source.Replace(newLinePlaceHolder + " ", newLinePlaceHolder);
                //replace 3 NewLines with 2 NewLines
                while (Source.Contains(newLinePlaceHolder + newLinePlaceHolder + newLinePlaceHolder))
                    Source = Source.Replace(newLinePlaceHolder + newLinePlaceHolder + newLinePlaceHolder, newLinePlaceHolder + newLinePlaceHolder);
                //add the NewLines in again
                Source = Source.Replace(newLinePlaceHolder, Environment.NewLine);
                return Source;
            }
            catch (Exception)
            {
                return originalSource;
            }
        }

        public static string ReplaceTagValues(string Source)
        {
            string originalSource = Source;
            try
            {
                //Replace certain tags with newlines: leave the tags intact, they will be removed later
                foreach (string tag in new string[] { "<br", "<tr", "<div", "<p", "<li", "<span" })
                    Source = Source.Replace(tag, newLinePlaceHolder + tag);
                //Add a space the td tag to separate the text in cells after the tags have been removed
                foreach (string tag in new string[] { "<td" })
                    Source = Source.Replace(tag, " " + tag);
                return Source;
            }
            catch (Exception)
            {
                return originalSource;
            }
        }

        public static string RemoveTagsFromString(string Source, Dictionary<string, Regex[]> CleanerExpressions)
        {
            string originalSource = Source;
            try
            {
                foreach (string key in CleanerExpressions.Keys)
                {
                    Regex[] expressions =  CleanerExpressions[key];
                    Source = expressions[0].Replace(Source, "<" + key + ">");
                    Source = expressions[1].Replace(Source, "</" + key + ">");
                    Source = expressions[2].Replace(Source, string.Empty);
                }
                return Source;
            }
            catch (Exception)
            {
                return originalSource;
            }
        }

        public static NameStruct ResolveNames(string EmailAddress)
        {
            NameStruct nameStruct = new NameStruct();
            EmailAddress = EmailAddress.Replace("\"", string.Empty).Replace("'", string.Empty);
            //Looking for an string like "Donut Dumbledore <donutd@hogg.com>"
            if (EmailAddress.IndexOf("<") > 0)
            {
                string tempNameValue = EmailAddress.Substring(0, EmailAddress.IndexOf('<') - 1).Trim();
                if (tempNameValue.Contains(" "))
                {
                    nameStruct.FirstName = tempNameValue.Substring(0, tempNameValue.IndexOf(' ') - 1).Trim();
                    nameStruct.LastName = tempNameValue.Substring(tempNameValue.IndexOf(' ')).Trim();
                }
                else
                {
                    nameStruct.FirstName = tempNameValue;
                    nameStruct.LastName = string.Empty;
                }
            }
            else
            {
                nameStruct.FirstName = GetPartFromEmail(EmailAddress, PartType.FirstName);
                nameStruct.LastName = GetPartFromEmail(EmailAddress, PartType.LastName);
            }
            return nameStruct;
        }

        private static string GetPartFromEmail(string EmailAddress, PartType TypeToReturn)
        {
            EmailAddress = EmailAddress.Trim();
            if (EmailAddress.IndexOf("@") < 0)
                return string.Empty;

            string emailAddressName = EmailAddress.Substring(0, EmailAddress.IndexOf("@"));
            string emailAddressDomain = EmailAddress.Replace(emailAddressName + "@", "");

            string firstName = string.Empty;
            string lastName = string.Empty;
            string fullname = string.Empty;
            if (emailAddressName.Contains("."))
            {
                firstName = ProperCase(StripPunctuation(emailAddressName.Substring(0, emailAddressName.IndexOf("."))));
                lastName = ProperCase(StripPunctuation(emailAddressName.Substring(emailAddressName.IndexOf(".") + 1, emailAddressName.Length - emailAddressName.IndexOf(".") - 1)));
                fullname = firstName + " " + lastName;
            }
            else
            {
                firstName = ProperCase(StripPunctuation(emailAddressName));
                lastName = string.Empty;
                fullname = firstName;
            }

            switch (TypeToReturn)
            {
                case PartType.Fullname:
                    return fullname;
                case PartType.FirstName:
                    return firstName;
                case PartType.LastName:
                    return lastName;
                case PartType.CompanyName:
                    if (emailAddressDomain.IndexOf(".") > 0)
                        return ProperCase(emailAddressDomain.Substring(0, emailAddressDomain.IndexOf(".")));
                    else
                        return ProperCase(emailAddressDomain);
                case PartType.Url:
                    return "http://www." + emailAddressDomain;
                default:
                    return string.Empty;
            }
        }

        public static string ProperCase(string Source)
        {
            string originalSource = Source;
            try
            {
                StringBuilder sb = new System.Text.StringBuilder();
                bool emptyBefore = true;
                foreach (char ch in Source)
                {
                    char chThis = ch;
                    if (Char.IsWhiteSpace(chThis))
                        emptyBefore = true;
                    else
                    {
                        if (Char.IsLetter(chThis) && emptyBefore)
                            chThis = Char.ToUpper(chThis);
                        else
                            chThis = Char.ToLower(chThis);
                        emptyBefore = false;
                    }
                    sb.Append(chThis);
                }
                return sb.ToString();
            }
            catch (Exception)
            {
                return originalSource;
            }
        }

        public static void SendNetMail(string Subject, string Body, string SendTo, string SendToBcc, string SendFrom, bool Html)
        {
            string functionName = "QueueManagerHelper SendNetMail: ";
            Logger.Write(functionName + "Enter", "Trace", 3);
            Logger.Write(functionName + "Parameter: Subject: " + Subject, "Trace", 1);
            Logger.Write(functionName + "Parameter: Body: " + Body, "Trace", 1);
            Logger.Write(functionName + "Parameter: SendTo: " + SendTo, "Trace", 1);
            Logger.Write(functionName + "Parameter: SendToBcc: " + SendToBcc, "Trace", 1);
            Logger.Write(functionName + "Parameter: SendFrom: " + SendFrom, "Trace", 1);
            Logger.Write(functionName + "Parameter: Html: " + Html.ToString(), "Trace", 1);
            try
            {
                MailMessage mailMessage = new MailMessage(SendFrom, SendTo);
                SmtpClient smtpClient = new SmtpClient();
                mailMessage.Body = Body;
                mailMessage.Subject = Subject;
                mailMessage.IsBodyHtml = Html;
                if (!string.IsNullOrEmpty(SendToBcc))
                    mailMessage.Bcc.Add(SendToBcc);
                //Workaround for Google
                if (smtpClient.Host.Contains("gmail"))
                    smtpClient.EnableSsl = true;
                smtpClient.Send(mailMessage);
            }
            catch (Exception ex)
            {
                Logger.Write(functionName + "Error: " + ex.ToString(), "Error", 5, 999, TraceEventType.Error);
                throw;
            }
            finally
            {
                Logger.Write(functionName + "Exit", "Trace", 3);
            }
        }
    }
}
